package model;

import control.ControllerPrincipal;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import tools.Coord;
import vinciappli.CardId;
import vinciappli.ProvinceSubType;
import vinciappli.StaticParams;


public class Province extends Zone {

    private String fieldType;
    private Set<ProvinceSubType> subtypes = new HashSet<ProvinceSubType>();
    /* Troops and fort placed on the province */
    private Map<String, Integer> territoryOccupation;
    /* Number of troops needed to conquest the province (related to its type) */
    private int conquestNeededTroops;

    public Province(int num, String type, Set<ProvinceSubType> subtypes, Map<String, Integer> territoryOccupation, Coord c) {
        super(num, c);
        this.fieldType = type;
        this.subtypes = subtypes;
        this.territoryOccupation = territoryOccupation;
        if(type.equals(StaticParams.PROVINCE_FIELDTYPE_MOUNTAIN) || type.equals(StaticParams.PROVINCE_FIELDTYPE_FOREST))
        {
            conquestNeededTroops = 3;
        }
        else
        {
            conquestNeededTroops = 2;
        }
    }

    /**
     * Add or take back troops from a province
     * @param nbTroops : Amount of troops to move
     * @param p : Player who has to move his troops through his empire
     */
    public void moveTroops(int nbTroops, Player p)
    {
        territoryOccupation.put(p.getNickname(), territoryOccupation.get(p.getNickname()) + nbTroops);
        p.setAvailableTroopsFromCurrentNumber(-nbTroops);
    }

    /**
     * Reset a province occupation that would be left by its last owner
     */
    public void leave()
    {
        Player p = ControllerPrincipal.getINSTANCE().getControllerPlayer().getPlayerFromProvince(this);
        int nbTroops = territoryOccupation.get(p.getNickname());
        territoryOccupation.remove(p.getNickname());
        territoryOccupation.put(StaticParams.PAWN_TYPE_FORT, 1);
        p.setAvailableTroopsFromCurrentNumber(nbTroops);
    }

    /**
     * Make the change on a province that would be conquered
     * @param assailant : Player who's conquering the province
     * @param nbTroops : Amount of troops moved to the province
     */
    public void beConquered (Player assailant, int nbTroops) {
        Player assailed = ControllerPrincipal.getINSTANCE().getControllerPlayer().getPlayerFromProvince(this);
                
        if(assailed != null)
        {
            ControllerPrincipal.getINSTANCE().getControllerGameBoard().getIdleTroops().put(assailed, territoryOccupation.get(assailed.getNickname()) - 1);
            territoryOccupation.put(assailed.getNickname(), 1);
            
            assailed.setTroopsFromCurrentNumber(-1);
            if(assailed.getNbTroops() == 0)
            {
                ControllerPrincipal.getINSTANCE().goDepress(assailed.getEmpire(false));
            }
        }
        territoryOccupation.remove(StaticParams.PAWN_TYPE_FORT);
        
        if(assailant.getEmpire(false).getCivilization().isComposedOf(CardId.esclavage))
        {
            ControllerPrincipal.getINSTANCE().getControllerGameBoard().setAssaultBonusPtsFromCurrentValue(1);
        }
        territoryOccupation.put(assailant.getNickname(), nbTroops);
    }

    /**
     * Return the total amount of pawns on the province (fort, enemies troops,...)
     * @param p : The province that is gonna be conquered
     * @return nb : The amount of forces on the province
     */
    public int getNeededTroopsToConquest(Province p)
    {
        int nb = 0;
        for(Entry<String, Integer> entry : territoryOccupation.entrySet())
        {
                nb += entry.getValue();
        }
        return nb;
    }

    /***************************** GETTERS & SETTERS **************************/
    
    public Map<String, Integer> getTerritoryOccupation () {
        return territoryOccupation;
    }

    public int getConquestNeededTroops () {
        return conquestNeededTroops;
    }

    public String getFieldType() {
        return fieldType;
    }

    public Set<ProvinceSubType> getSubtypes() {
        return subtypes;
    }

}

